/*
 * MIT License
 *
 * Copyright (c) 2023 北京凯特伟业科技有限公司
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */
package com.je.rbac.service.grant.role.impl;

import com.beust.jcommander.internal.Lists;
import com.google.common.base.Strings;
import com.je.common.base.DynaBean;
import com.je.common.base.service.CommonService;
import com.je.common.base.service.MetaService;
import com.je.ibatis.extension.conditions.ConditionsWrapper;
import com.je.rbac.service.grant.role.RbacGrantRoleMenuPermmisionService;
import com.je.rbac.service.permission.GrantMethodEnum;
import com.je.rbac.service.permission.GrantTypeEnum;
import com.je.rbac.service.permission.template.PcMenuDataService;
import com.je.rbac.service.role.RbacRoleService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;

@Service
public class RbacGrantRoleMenuPermmisionServiceImpl implements RbacGrantRoleMenuPermmisionService {

    @Autowired
    private MetaService metaService;
    @Autowired
    private CommonService commonService;
    @Autowired
    private PcMenuDataService pcMenuDataService;
    @Autowired
    private RbacRoleService rbacRoleService;

    @Override
    @Transactional(rollbackFor = RuntimeException.class)
    public void saveRoleMenuPermission(String roleId, String menuId, String excludeChecked, GrantTypeEnum grantType) {
        Map<DynaBean, String> allPermmissionBeanMap = new HashMap<>();
        allPermmissionBeanMap.put(pcMenuDataService.writeMenuDataShowTemplate(menuId, true), excludeChecked);
        //写入关联关系
        saveRolePermAssocaition(roleId, allPermmissionBeanMap, grantType);
    }

    @Override
    @Transactional(rollbackFor = RuntimeException.class)
    public void removeRoleMenuPermission(String roleId, String menuId, GrantTypeEnum grantType, boolean update, boolean delete) {
        List<String> menuPermissionList = new ArrayList<>();
        menuPermissionList.add(pcMenuDataService.formatMenuDataShowTemplate(menuId));
        if (update) {
            menuPermissionList.add(pcMenuDataService.formatMenuDataUpdateTemplate(menuId));
        }
        if (delete) {
            menuPermissionList.add(pcMenuDataService.formatMenuDataDeleteTemplate(menuId));
        }
        List<DynaBean> rolePermList = metaService.select("JE_RBAC_VROLEPERM", ConditionsWrapper.builder()
                .eq("ROLEPERM_GRANTTYPE_CODE", grantType.name())
                .eq("JE_RBAC_ROLE_ID", roleId)
                .in("PERM_CODE", menuPermissionList));
        List<String> menuPermissionIdList = new ArrayList<>();
        for (DynaBean eachRolePermBean : rolePermList) {
            menuPermissionIdList.add(eachRolePermBean.getStr("JE_RBAC_ROLEPERM_ID"));
        }
        metaService.delete("JE_RBAC_ROLEPERM", ConditionsWrapper.builder().in("JE_RBAC_ROLEPERM_ID", menuPermissionIdList));
    }

    @Override
    @Transactional(rollbackFor = RuntimeException.class)
    public void saveRoleMenuPermissions(String roleId, Map<String, String> menuIdMap, GrantTypeEnum grantType) {
        Map<DynaBean, String> allPermmissionBeanMap = new HashMap<>();
        for (String menuCode : menuIdMap.keySet()) {
            allPermmissionBeanMap.put(pcMenuDataService.writeMenuDataShowTemplate(menuCode, true), menuIdMap.get(menuCode));
        }
        saveRolePermAssocaition(roleId, allPermmissionBeanMap, grantType);
    }

    @Override
    public void removeRoleMenuPermissions(String roleId, List<String> menuIdList, GrantTypeEnum grantType, boolean update, boolean delete) {
        List<String> menuPermissionList = new ArrayList<>();
        for (String eachMenuCode : menuIdList) {
            menuPermissionList.add(pcMenuDataService.formatMenuDataShowTemplate(eachMenuCode));
            if (update) {
                menuPermissionList.add(pcMenuDataService.formatMenuDataUpdateTemplate(eachMenuCode));
            }
            if (delete) {
                menuPermissionList.add(pcMenuDataService.formatMenuDataDeleteTemplate(eachMenuCode));
            }
        }

        List<DynaBean> rolePermList = metaService.select("JE_RBAC_VROLEPERM", ConditionsWrapper.builder()
                .eq("ROLEPERM_GRANTTYPE_CODE", grantType.name())
                .eq("JE_RBAC_ROLE_ID", roleId)
                .in("PERM_CODE", menuPermissionList));
        List<String> menuPermissionIdList = new ArrayList<>();
        for (DynaBean eachRolePermBean : rolePermList) {
            menuPermissionIdList.add(eachRolePermBean.getStr("JE_RBAC_ROLEPERM_ID"));
        }
        metaService.delete("JE_RBAC_ROLEPERM", ConditionsWrapper.builder().in("JE_RBAC_ROLEPERM_ID", menuPermissionIdList));
    }

    /**
     * 保存关系
     *
     * @param roleId
     * @param permissionMap
     */
    private void saveRolePermAssocaition(String roleId, Map<DynaBean, String> permissionMap, GrantTypeEnum grantType) {
        //查询已存在的关联关系
        List<String> permissionIdList = new ArrayList<>();
        //如果是排他权限，则设置check或不check，因为他不会受其他影响
        Map<String, String> haveExcludeRolePermissionMap = new HashMap<>();
        for (DynaBean eachPermissionBean : permissionMap.keySet()) {
            if (!Strings.isNullOrEmpty(permissionMap.get(eachPermissionBean))) {
                if("0".equals(permissionMap.get(eachPermissionBean)) || "false".equals(permissionMap.get(eachPermissionBean))){
                    haveExcludeRolePermissionMap.put(eachPermissionBean.getStr("JE_RBAC_PERM_ID"), "1");
                }else{
                    haveExcludeRolePermissionMap.put(eachPermissionBean.getStr("JE_RBAC_PERM_ID"), "0");
                }
            }
            permissionIdList.add(eachPermissionBean.getStr("JE_RBAC_PERM_ID"));
        }
        Set<String> extendRoleIdList = rbacRoleService.findExtendRoleIds(Lists.newArrayList(roleId));
        extendRoleIdList.add(roleId);

        List<DynaBean> associationList = metaService.select("JE_RBAC_ROLEPERM", ConditionsWrapper.builder()
                .eq("ROLEPERM_GRANTTYPE_CODE", grantType.name())
                .in("JE_RBAC_ROLE_ID", extendRoleIdList)
                .in("JE_RBAC_PERM_ID", permissionIdList));
        List<String> havedRolePermissionList = new ArrayList<>();
        for (DynaBean eachAssociationBean : associationList) {
            if("0".equals(eachAssociationBean.getStr("ROLEPERM_EXCLUDE_CODE"))
                    && haveExcludeRolePermissionMap.containsKey(eachAssociationBean.getStr("JE_RBAC_PERM_ID"))){
                haveExcludeRolePermissionMap.remove(eachAssociationBean.getStr("JE_RBAC_PERM_ID"));
            }
            havedRolePermissionList.add(eachAssociationBean.getStr("JE_RBAC_PERM_ID"));
        }
        //写入关联关系
        DynaBean rolePermBean;
        for (DynaBean eachPermissionBean : permissionMap.keySet()) {
            //如果是正常权限，不是排他权限，则不做任何处理，如果是排他权限，则需要设置ROLEPERM_NOT_CHECKED
            if (havedRolePermissionList.contains(eachPermissionBean.getStr("JE_RBAC_PERM_ID"))) {
                if(haveExcludeRolePermissionMap.containsKey(eachPermissionBean.getStr("JE_RBAC_PERM_ID"))){
                    metaService.executeSql("UPDATE JE_RBAC_ROLEPERM SET ROLEPERM_NOT_CHECKED = {0} WHERE JE_RBAC_ROLE_ID={1} AND JE_RBAC_PERM_ID={2}",
                            haveExcludeRolePermissionMap.get(eachPermissionBean.getStr("JE_RBAC_PERM_ID")),
                            roleId,
                            eachPermissionBean.getStr("JE_RBAC_PERM_ID"));
                }
                continue;
            }

            rolePermBean = new DynaBean("JE_RBAC_ROLEPERM", false);
            rolePermBean.set("JE_RBAC_ROLE_ID", roleId);
            rolePermBean.set("JE_RBAC_PERM_ID", eachPermissionBean.getStr("JE_RBAC_PERM_ID"));
            rolePermBean.set("ROLEPERM_EXCLUDE_CODE", "0");
            rolePermBean.set("ROLEPERM_EXCLUDE_NAME", "否");
            //授权方式
            rolePermBean.set("ROLEPERM_TYPE_CODE", GrantMethodEnum.ROLE.name());
            rolePermBean.set("ROLEPERM_TYPE_NAME", GrantMethodEnum.ROLE.getDesc());
            //授权类型
            rolePermBean.set("ROLEPERM_GRANTTYPE_CODE", grantType.name());
            rolePermBean.set("ROLEPERM_GRANTTYPE_NAME", grantType.getDesc());
            //todo 设置租户信息
            commonService.buildModelCreateInfo(eachPermissionBean);
            metaService.insert(rolePermBean);
        }
    }

}
